/*
 * author      : 吴中勤 
 * date        : 2018/8/16
 * description : 负责维护 (moby-SAP) BP的关系
 */

package com.deepexi.adapter.converter.sap.bp;

import com.deepexi.adapter.common.exception.HttpNon200Exception;
import com.deepexi.adapter.common.sdk.RequestInfo;
import com.deepexi.adapter.converter.sap.SapConverterContext;
import com.deepexi.adapter.converter.sap.SapSdkIntercepter;
import com.deepexi.adapter.facade.moby.request.MobyEventBody;
import com.deepexi.adapter.sdk.sap.SapRecords;
import com.deepexi.adapter.sdk.sap.SapSdk;
import com.deepexi.adapter.sdk.sap.dto.bp.BPOutputVO;
import com.deepexi.adapter.sdk.sap.dto.bp.SapBPResponseBody;
import com.deepexi.adapter.sdk.sap.dto.bp.create.SapBPCreateRequestBody;
import com.deepexi.adapter.sdk.sap.dto.bp.extend.SapBPExtendRequestBody;
import com.deepexi.adapter.sdk.sap.exception.SapBizException;
import org.json.JSONException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class BPService {

    @Autowired
    private SapSdkIntercepter sapSdkIntercepter;

    @Autowired
    private SapAdapterMemberMapper sapAdapterMemberMapper;

    @Autowired
    private BPRequestAssembler bpRequestAssembler;

    @Autowired
    private SapSdk sapSdk;

    @Autowired
    private SapConverterContext sapConverterContext;

    private static final Logger logger = LoggerFactory.getLogger(BPService.class);

    /**
     * 处理 维护BP信息, 处理 新建/扩展
     * 创建BP逻辑
     * - 首先判断BP是否已创建(查询本地数据库, memberId 对应的记录是否已经存在
     * - - 不存在, 则创建， 记录 memberId - BP_NUM - 门店号 - 客户顾问 对应关系
     * - - 已经存在, 看 有没有 memberId - 门店号
     * - - - - 已有 memberId - 门店号, 不需要创建BP
     * - - - - 没有 memberId - 门店号, 对这个BP进行扩展(BP扩展接口)
     *
     * @param body
     * @return BP_NUM
     * @throws IOException JSONException
     */
    public SapAdapterMember createOrExtendBPIfNesessary(MobyEventBody body)
            throws IOException, JSONException, SapBizException, HttpNon200Exception {

        String memberId = body.getMobyMember().getId();
        List<SapAdapterMember> adapterMemberList = sapAdapterMemberMapper.listByMember(memberId);
        String shopCode = body.getMobyTradeOrder().getShopCode();

        if (0 == adapterMemberList.size()) {
            sapConverterContext.getLogContext().setKeyword1("创建BP");
            logger.info("创建BP");
            return createBP2Sap(body);
        }

        // 扩展BP
        List<SapAdapterMember> inShopList = adapterMemberList
                .stream()
                .filter(sapAdapterMember -> shopCode.equals(sapAdapterMember.getShopCode()))
                .collect(Collectors.toList());
        if (0 == inShopList.size()) {
            sapConverterContext.getLogContext().setKeyword1("扩展BP");
            logger.info("扩展BP");
            return extendBP2Sap(body, inShopList.get(0));
        } else {
            logger.info("此member对应的BP已经存在, 无需创建和扩展");
            return inShopList.get(0);
        }
    }

    // 新建BP
    private SapAdapterMember createBP2Sap(MobyEventBody body)
            throws IOException, JSONException, SapBizException, HttpNon200Exception {
        logger.info("需要新建BP");
        SapBPCreateRequestBody requestBody = bpRequestAssembler.assembleCreateBP(body);

        RequestInfo requestInfo = sapSdk.requestInfo4BPCreate(new SapRecords<SapBPCreateRequestBody>(requestBody));
        String respBodyStr = sapSdkIntercepter.doHttpAndLogWithRetryIfFail(requestInfo);    // 日志和重试
        SapBPResponseBody responseBody = sapSdk.parseResult(requestInfo, respBodyStr);

        BPOutputVO bpItem = checkResponseBody(responseBody, "创建BP失败:");
        logger.info("新建BP成功");

        return saveBP(body, bpItem);
    }

    // 扩展BP
    private SapAdapterMember extendBP2Sap(MobyEventBody body, SapAdapterMember extendsFrom)
            throws IOException, JSONException, SapBizException, HttpNon200Exception {
        logger.info("扩展BP");

        // 组装请求体 -> 发请求
        SapBPExtendRequestBody requestBody = bpRequestAssembler.assembleExtendBP(body, extendsFrom);
        RequestInfo requestInfo = sapSdk.requestInfo4BPExtend(new SapRecords<SapBPExtendRequestBody>(requestBody));
        String respBodyStr = sapSdkIntercepter.doHttpAndLogWithRetryIfFail(requestInfo);    // 日志和重试
        SapBPResponseBody responseBody = sapSdk.parseResult(requestInfo, respBodyStr);

        BPOutputVO bpItem = checkResponseBody(responseBody, "扩展BP失败:");
        logger.info("扩展成功");

        return saveBP(body, bpItem);
    }

    // 检测BP接口返回结果
    private BPOutputVO checkResponseBody(SapBPResponseBody responseBody, String errInfo) throws SapBizException {
        if (null == responseBody || !responseBody.isOk()) {
            throw new SapBizException(errInfo + responseBody.toString());
        }

        // 处理结果
        List<BPOutputVO> bpItemList = responseBody.getBPItems();
        if (null == bpItemList || 0 == bpItemList.size()) {
            throw new SapBizException("SAP BP接口出错: " + errInfo + responseBody.toString());
        }

        BPOutputVO bpItem = bpItemList.get(0);
        if (!bpItem.isOk()) {
            throw new SapBizException("SAP BP接口出错: " + errInfo + bpItem.toString());
        }
        return bpItem;
    }

    // 存储BP-member的关系
    private SapAdapterMember saveBP(MobyEventBody body, BPOutputVO bpOutputVO) {
        SapAdapterMember memberBP = new SapAdapterMember();
        memberBP.setMemberId(body.getMobyMember().getId());
        memberBP.setBpNum(bpOutputVO.getBpNum());
        memberBP.setShopCode(body.getMobyTradeOrder().getShopCode());
        memberBP.setMemberName(body.getMobyMember().getName());
        sapAdapterMemberMapper.insert(memberBP);
        return memberBP;
    }
}
